<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Edit, Delete } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
import { useTokenStore } from '@/stores/token'
import { Download } from '@element-plus/icons-vue'; // 导入 Download 图标组件
const tokenStore = useTokenStore()

interface ScrapRequest {
  id: number
  serialNumber: string
  applicantId: number
  departmentName: string
  reason: string
  scrapType: string
  scrapFileUrl: string
  status: string
  submitTime: string
  updateTime: string
}

interface ScrapRequestListResponse {
  current: number
  total: number
  pages: number
  size: number
  records: ScrapRequest[]
}

interface ScrapRequestModel {
  serialNumber: string | null
  applicantId: number | null
  departmentName: string | null
  reason: string | null
  scrapType: string | null
  scrapFileUrl: string | null
}

const scrapTypeMap = {
  '使用年限到期': '使用年限到期',
  '损坏无法修复': '损坏无法修复',
  '维修成本过高': '维修成本过高'
} as const

const statusTypeMap = {
  '待审批': '待审批',
  '已通过': '已通过',
  '已驳回': '已驳回'
} as const

const departmentOptions = [
  { label: '医疗设备科', value: '医疗设备科' },
  { label: '信息科', value: '信息科' },
  { label: '临床科室', value: '临床科室' },
  { label: '财务科', value: '财务科' },
  { label: '采购科', value: '采购科' },
  { label: '设备验收组', value: '设备验收组' },
  { label: '资产管理科', value: '资产管理科' },
  { label: '护理部', value: '护理部' },
  { label: '科教科', value: '科教科' },
  { label: '院领导办公室', value: '院领导办公室' },
  { label: '维修保障中心', value: '维修保障中心' },
  { label: '安全保障部', value: '安全保障部' },
  { label: '后勤保障部', value: '后勤保障部' },
  { label: '检验科', value: '检验科' },
  { label: '放射科', value: '放射科' },
  { label: '超声科', value: '超声科' }
]

const getScrapTypeLabel = (value: string): string => {
  return scrapTypeMap[value as keyof typeof scrapTypeMap] || '未知类型'
}

const getStatusTypeLabel = (value: string): string => {
  return statusTypeMap[value as keyof typeof statusTypeMap] || '未知状态'
}

const scrapApi = {
  getScrapList: (params: any) => request<ScrapRequestListResponse>({
    method: 'GET',
    url: '/scrap/list',
    params
  }),
  addScrap: (data: ScrapRequestModel) => request<string>({
    method: 'POST',
    url: '/scrap/submit',
    data
  }),
  updateScrap: (id: number, data: ScrapRequestModel) => request<string>({
    method: 'PUT',
    url: `/scrap/${id}`,
    data
  }),
  deleteScrap: (id: number) => request<string>({
    method: 'DELETE',
    url: `/scrap/${id}`
  }),
  uploadFile: (file: File) => {
    const formData = new FormData()
    formData.append('file', file)
    return request<string>({
      method: 'POST',
      url: '/scrap/uploadFile',
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
  },
  getSerialSuggestions: (keyword: string) => request<string[]>({
    method: 'GET',
    url: '/device/serial/suggestions',
    params: { keyword }
  })
}

const scrapRequestList = ref<ScrapRequest[]>([])
const formModel = ref<ScrapRequestModel>({
  serialNumber: null,
  applicantId: tokenStore.id || null,
  departmentName: (tokenStore as any).departmentName || null,
  reason: null,
  scrapType: null,
  scrapFileUrl: null
})

const currentEditId = ref<number | null>(null)
const serialNumberOptions = ref<string[]>([])
const loadingSerialNumbers = ref(false)
const fileList = ref<any[]>([])
const isSubmitting = ref(false)

const titleName = '设备报废管理'
const bufferName = [{ add: '添加报废申请' }, { edit: '编辑报废申请' }]
const title = ref('')
const visibleDrawer = ref(false)

const searchMessage = ref({
  serialNumber: null as string | null,
  status: null as string | null,
  scrapType: null as string | null
})

const pageNum = ref(1)
const pageSize = ref(10)
const total = ref(0)

onMounted(() => {
  getDataListWithCondition()
})

const fetchSerialSuggestions = async (query: string) => {
  if (query) {
    loadingSerialNumbers.value = true
    try {
      const res = await scrapApi.getSerialSuggestions(query)
      serialNumberOptions.value = res.data
    } catch {
      ElMessage.error('获取设备序列号失败')
    } finally {
      loadingSerialNumbers.value = false
    }
  } else {
    serialNumberOptions.value = []
  }
}

const getDataListWithCondition = async () => {
  const params: any = {
    page: pageNum.value,
    size: pageSize.value,
    serialNumber: searchMessage.value.serialNumber,
    status: searchMessage.value.status,
    type: searchMessage.value.scrapType,
    applicantId: tokenStore.id
  }

  Object.keys(params).forEach(key => {
    if (params[key] === null || params[key] === undefined || params[key] === '') {
      delete params[key]
    }
  })

  try {
    const res = await scrapApi.getScrapList(params)
    scrapRequestList.value = res.data.records
    total.value = res.data.total
  } catch (error) {
    ElMessage.error('获取数据失败')
  }
}

const downloadFile = (url: string) => {
  if (!url) {
    ElMessage.warning('没有可下载的附件')
    return
  }
  
  const link = document.createElement('a')
  link.href = url
  link.target = '_blank'
  link.download = url.split('/').pop() || 'attachment'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

const handleSubmit = async () => {
  if (isSubmitting.value) return
  
  try {
    isSubmitting.value = true
    
    if (!formModel.value.serialNumber || !formModel.value.scrapType || !formModel.value.reason || !formModel.value.departmentName) {
      ElMessage.warning('请填写完整信息')
      return
    }
    
    if (fileList.value.length > 0 && fileList.value[0].raw) {
      try {
        const file = fileList.value[0].raw
        const uploadResponse = await scrapApi.uploadFile(file)
        formModel.value.scrapFileUrl = (uploadResponse as any).message
      } catch (uploadError) {
        ElMessage.error('文件上传失败')
        return
      }
    } else if (!formModel.value.scrapFileUrl) {
      ElMessage.warning('请上传证明文件')
      return
    }
    
    if (currentEditId.value) {
      await scrapApi.updateScrap(currentEditId.value, formModel.value)
      ElMessage.success('修改成功')
    } else {
      await scrapApi.addScrap(formModel.value)
      ElMessage.success('提交成功')
    }
    
    visibleDrawer.value = false
    getDataListWithCondition()
  } catch (error) {
    ElMessage.error(currentEditId.value ? '修改失败' : '提交失败')
  } finally {
    isSubmitting.value = false
  }
}

const clearData = () => {
  currentEditId.value = null
  formModel.value = {
    serialNumber: null,
    applicantId: tokenStore.id || null,
    departmentName: (tokenStore as any).departmentName || null,
    reason: null,
    scrapType: null,
    scrapFileUrl: null
  }
  fileList.value = []
}

const showAddDrawer = () => {
  clearData()
  title.value = bufferName[0].add!
  visibleDrawer.value = true
}

const showEditDrawer = (row: ScrapRequest) => {
  clearData()
  currentEditId.value = row.id
  title.value = bufferName[1].edit!
  visibleDrawer.value = true
  formModel.value = {
    serialNumber: row.serialNumber,
    applicantId: row.applicantId,
    departmentName: row.departmentName,
    reason: row.reason,
    scrapType: row.scrapType,
    scrapFileUrl: row.scrapFileUrl
  }
  if (row.scrapFileUrl) {
    fileList.value = [{
      name: row.scrapFileUrl.split('/').pop(),
      url: row.scrapFileUrl
    }]
  }
}

const deleteBox = async (id: number) => {
  try {
    await ElMessageBox.confirm('您确定要删除这条记录吗', '注意', {
      confirmButtonText: '删除',
      cancelButtonText: '取消',
      type: 'warning'
    })
    await scrapApi.deleteScrap(id)
    ElMessage.success('删除成功')
    getDataListWithCondition()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败')
    }
  }
}

const search = () => {
  pageNum.value = 1
  getDataListWithCondition()
}

const searchWithNoCondition = () => {
  searchMessage.value = {
    serialNumber: null,
    status: null,
    scrapType: null
  }
  pageNum.value = 1
  getDataListWithCondition()
}

const onSizeChange = (size: number) => {
  pageSize.value = size
  getDataListWithCondition()
}

const onCurrentChange = (num: number) => {
  pageNum.value = num
  getDataListWithCondition()
}

const tableRowClassName = ({ row }: { row: ScrapRequest }) => {
  if (row.status === '待审批') return 'pending-row'
  if (row.status === '已通过') return 'approved-row'
  if (row.status === '已驳回') return 'rejected-row'
  return ''
}
const isImage = (file: any): boolean => {
  const name = file.name || ''
  return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(name)
}

const getFileUrl = (file: any): string => {
  return file.url || URL.createObjectURL(file.raw)
}
const isImageFile = (url: string): boolean => {
  return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(url)
}


</script>

<template>
  <!-- <div class="maintenance-wrapper"> -->
    <el-card class="card-box">
      <!-- <template #header> -->
        <div class="header">
          <h2>{{ titleName }}</h2>
          <el-button type="primary" @click="showAddDrawer">{{ bufferName[0].add }}</el-button>
        </div>
      <!-- </template> -->

      <el-form inline class="filter-bar">
        <el-form-item label="设备ID:">
          <el-select
            v-model="searchMessage.serialNumber"
            filterable remote clearable reserve-keyword
            placeholder="请输入设备ID"
            :remote-method="fetchSerialSuggestions"
            :loading="loadingSerialNumbers"
            class="input-short"
          >
            <el-option
              v-for="item in serialNumberOptions"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="状态:">
          <el-select
            v-model="searchMessage.status"
            placeholder="请选择状态"
            clearable
            class="input-short"
          >
            <el-option
              v-for="item in Object.values(statusTypeMap)"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="报废类型:">
          <el-select
            v-model="searchMessage.scrapType"
            placeholder="请选择报废类型"
            clearable
            class="input-short"
          >
            <el-option
              v-for="item in Object.values(scrapTypeMap)"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="search">搜索</el-button>
          <el-button @click="searchWithNoCondition">重置</el-button>
        </el-form-item>
      </el-form>

      <div class="responsive-table-container">
        <table class="custom-table">
          <thead>
            <tr>
              <th>编号</th>
              <th>设备ID</th>
              <th>申请人ID</th>
              <th>部门</th>
              <th>报废原因</th>
              <th>报废类型</th>
              <th>附件</th>
              <th>状态</th>
              <th>提交时间</th>
              <th>更新时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr 
              v-for="item in scrapRequestList" 
              :key="item.id"
              :class="tableRowClassName({ row: item })"
            >
              <td>{{ item.id }}</td>
              <td>{{ item.serialNumber }}</td>
              <td>{{ item.applicantId }}</td>
              <td>{{ item.departmentName }}</td>
              <td class="truncate">{{ item.reason }}</td>
              <td>{{ getScrapTypeLabel(item.scrapType) }}</td>
             <td>
  <template v-if="item.scrapFileUrl">
    <template v-if="isImageFile(item.scrapFileUrl)">
      <el-popover
        placement="left"
        trigger="hover"
        :width="325"
        popper-class="image-popover"
      >
        <template #reference>
          <img
            :src="item.scrapFileUrl"
            class="thumbnail-img"
            alt="缩略图"
            @click="downloadFile(item.scrapFileUrl)"
          />
        </template>
        <img :src="item.scrapFileUrl" class="preview-img" alt="大图预览" />
      </el-popover>
      <a
        :href="item.scrapFileUrl"
        :download="item.scrapFileUrl.split('/').pop()"
        class="thumbnail-download"
        title="点击下载"
      />
    </template>
    <el-button
      v-else
      :icon="Download"
      type="primary"
      link
      @click="downloadFile(item.scrapFileUrl)"
    >
      下载附件
    </el-button>
  </template>
  <span v-else class="no-attachment">无附件</span>
</td>

              <td>
                <el-tag :type="item.status === '已通过' ? 'success' : item.status === '已驳回' ? 'danger' : 'warning'">
                  {{ getStatusTypeLabel(item.status) }}
                </el-tag>
              </td>
              <td>{{ item.submitTime }}</td>
              <td>{{ item.updateTime }}</td>
              <td>
                <div class="action-btns">
                  <el-button
                    :icon="Edit"
                     circle
                     plain
                     size="small"
                    :type="item.status === '待审批' ? 'primary' : 'info'"
                    :disabled="item.status !== '待审批'"
                     @click="item.status === '待审批' && showEditDrawer(item)"
    />
                  <el-button
                    :icon="Delete"
                    circle
                    plain
                    size="small"
                    type="danger"
                    @click="deleteBox(item.id)"
                  />
                </div>
              </td>
            </tr>
            <tr v-if="scrapRequestList.length === 0">
              <td colspan="11" class="text-center py-4">
                <el-empty description="暂无数据" />
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="pagination-container">
        <el-pagination
          v-model:current-page="pageNum"
          v-model:page-size="pageSize"
          :page-sizes="[3, 5, 7, 10]"
          layout="total, sizes, prev, pager, next, jumper"
          background
          :total="total"
          @size-change="onSizeChange"
          @current-change="onCurrentChange"
        />
      </div>
    </el-card>

    <el-drawer 
      v-model="visibleDrawer" 
      :title="title" 
      direction="rtl" 
      size="50%"
    >
      <el-form :model="formModel" label-width="120px" class="drawer-form">
        <el-form-item label="设备ID" required>
          <el-select
            v-model="formModel.serialNumber"
            filterable remote clearable reserve-keyword
            placeholder="请搜索并选择设备ID"
            :remote-method="fetchSerialSuggestions"
            :loading="loadingSerialNumbers"
            class="w-full"
          >
            <el-option 
              v-for="item in serialNumberOptions" 
              :key="item" 
              :label="item" 
              :value="item" 
            />
          </el-select>
        </el-form-item>
        <el-form-item label="部门" required>
          <el-select
            v-model="formModel.departmentName"
            placeholder="请选择部门"
            class="w-full"
          >
            <el-option
              v-for="item in departmentOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="报废类型" required>
          <el-select
            v-model="formModel.scrapType"
            placeholder="请选择报废类型"
            class="w-full"
          >
            <el-option
              v-for="item in Object.values(scrapTypeMap)"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="报废原因" required>
          <el-input
            v-model="formModel.reason"
            type="textarea"
            :rows="3"
            placeholder="请输入报废原因"
          />
        </el-form-item>
        <el-form-item label="证明文件" required>
          <el-upload
            v-model:file-list="fileList"
            accept="image/*,.pdf,.doc,.docx"
            :limit="1"
            :auto-upload="false"
            :on-exceed="() => ElMessage.warning('只能上传一个文件')"
            class="w-full"
          >
            <el-button type="primary">选择文件</el-button>
           <template #tip>
  <div class="el-upload__tip">
    请上传图片、PDF或Word文档
    <div v-if="fileList.length > 0" class="file-preview-wrapper">
      <a
        :href="getFileUrl(fileList[0])"
        target="_blank"
        class="file-preview"
        @click.stop
      >
        <img
          v-if="isImage(fileList[0])"
          :src="getFileUrl(fileList[0])"
          class="preview-img"
          alt="预览"
        />
        <span v-else class="file-name">{{ fileList[0].name }}</span>

        <!-- 悬浮放大框在左侧显示 -->
        <div class="file-hover-preview left-preview">
          <img
            v-if="isImage(fileList[0])"
            :src="getFileUrl(fileList[0])"
            class="zoom-img"
            alt="大图预览"
          />
          <span v-else class="zoom-text">{{ fileList[0].name }}</span>
        </div>
      </a>
    </div>
  </div>
</template>


          </el-upload>
        </el-form-item>
        <el-form-item>
          <el-button 
            type="primary" 
            @click="handleSubmit" 
            :disabled="isSubmitting"
            class="submit-btn"
          >
            {{ isSubmitting ? '提交中...' : '提交' }}
          </el-button>
        </el-form-item>
      </el-form>
    </el-drawer>
  <!-- </div> -->
</template>

<style lang="scss" scoped>
.maintenance-wrapper {
  min-height: 100vh;
  padding: 1rem;
  box-sizing: border-box;
  background-color: #f0f2f5;
  display: flex;
  justify-content: center;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  color: #2c3e50;
}

.card-box {
  width: 100%;
  max-width: 100%;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
}

.header {
  padding: 0.8rem 1.2rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #e6eaf0;
  background-color: #f7f9fc;
  h2 {
    font-weight: 600;
    font-size: 1.4rem;
    color: #333;
    user-select: none;
    margin: 0;
  }
  .el-button {
    min-width: 120px;
    font-weight: 500;
    height: 32px;
    padding: 0 12px;
  }
}

.filter-bar {
  padding: 0.8rem 1.2rem;
  background-color: #fafbfc;
  border-bottom: 1px solid #e6eaf0;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  overflow-x: auto;
  white-space: nowrap;
  gap: 0.8rem;

  .el-form-item {
    margin-bottom: 0 !important;
    flex-shrink: 0;
    label {
      font-weight: 500;
      color: #606266;
      font-size: 0.9rem;
    }
    .input-short {
      width: 160px;
    }
  }

  .el-button {
    height: 32px;
    font-weight: 500;
    padding: 0 12px;
    flex-shrink: 0;
  }
}

.responsive-table-container {
  overflow-x: auto;
  background: #fff;
  padding: 0.8rem;
}

.custom-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0 6px;
  font-size: 0.9rem;

  thead tr {
    background-color: #f5f7fa;
    color: #606266;
    font-weight: 600;
    user-select: none;
  }

  th, td {
    padding: 8px 12px;
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
  }

  th {
    font-size: 0.85rem;
  }

  tbody tr {
    background-color: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
    transition: background-color 0.2s ease;

    &:hover {
      background-color: #f4f9ff;
    }
  }

  .truncate {
    max-width: 180px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .action-btns {
    display: flex;
    gap: 0.4rem;

    .el-button {
      padding: 0;
      width: 28px;
      height: 28px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 50%;
    }
  }
}

.pending-row {
  background-color: #fff7e6;
}

.approved-row {
  background-color: #f0fbf7;
}

.rejected-row {
  background-color: #fff0f0;
}

.no-attachment {
  color: #a9abb0;
  font-style: italic;
  user-select: none;
  font-size: 0.85rem;
}

.pagination-container {
  background-color: #fafbfc;
  padding: 0.8rem;
  border-top: 1px solid #e6eaf0;
  display: flex;
  justify-content: center;
}

.el-drawer__body {
  padding: 1rem;
  background-color: #f9fafc;
}

.drawer-form {
  .el-form-item {
    margin-bottom: 1rem;

    label {
      font-weight: 500;
      color: #606266;
      font-size: 0.9rem;
    }

    .w-full {
      width: 100%;
    }
  }

  .submit-btn {
    width: 100%;
    font-weight: 500;
    height: 36px;
  }
}

.el-upload__tip {
  font-size: 0.8rem;
  color: #8c8c8c;
  margin-top: 4px;
  user-select: none;

  a {
    color: #409eff;
    text-decoration: underline;
    cursor: pointer;

    &:hover {
      color: #66b1ff;
    }
  }
}

@media (max-width: 1200px) {
  .filter-bar {
    gap: 0.6rem;
    
    .input-short {
      width: 140px;
    }
  }
  
  .custom-table {
    font-size: 0.85rem;
    
    th, td {
      padding: 6px 8px;
    }
  }
}

@media (max-width: 992px) {
  .header {
    padding: 0.6rem 1rem;
    
    h2 {
      font-size: 1.2rem;
    }
  }
  
  .filter-bar {
    padding: 0.6rem 1rem;
  }
  
  .responsive-table-container {
    padding: 0.6rem;
  }
}
.file-preview-wrapper {
  margin-top: 8px;
  display: flex;
  align-items: center;
  position: relative;
}

.file-preview {
  position: relative;
  display: inline-block;
  cursor: pointer;
  width: 80px;
  height: 80px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
  background-color: #f5f7fa;
  text-align: center;
  line-height: 80px;
  color: #606266;
  font-size: 12px;
  transition: border-color 0.3s ease;
}

.file-preview:hover {
  border-color: #409eff;
}

.preview-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.file-name {
  display: block;
  padding: 0 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-hover-preview {
  position: absolute;
  top: 0;
  z-index: 20;
  display: none;
  background: white;
  padding: 6px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  min-width: 120px;
  max-width: 200px;
  max-height: 200px;
  white-space: normal;
}

.left-preview {
  right: 100%; // 左侧显示
  margin-right: 10px;
}

.zoom-img {
  width: 100%;
  height: auto;
  max-height: 180px;
  object-fit: contain;
}

.zoom-text {
  color: #303133;
  font-size: 14px;
  word-break: break-all;
}

.file-preview:hover .file-hover-preview {
  display: block;
}
.attachment-thumbnail {
  display: inline-block;
  width: 40px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  vertical-align: middle;
}

.thumbnail-img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 4px;
  object-fit: cover;
  cursor: pointer;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease;
}

.thumbnail-img:hover {
  transform: scale(1.1);
}

.attachment-thumbnail {
  display: inline-block;
  width: 40px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  vertical-align: middle;
}

.thumbnail-img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 4px;
  object-fit: cover;
  cursor: pointer;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease;
}

.thumbnail-img:hover {
  transform: scale(1.1);
}
.thumbnail-img {
  width: 40px;
  height: 40px;
  border-radius: 4px;
  object-fit: cover;
  cursor: zoom-in;
  transition: transform 0.2s ease;
  margin-right: 4px;
  vertical-align: middle;
}

.thumbnail-img:hover {
  transform: scale(1.1);
}

.thumbnail-download {
  display: inline-block;
  width: 0;
  height: 0;
  overflow: hidden;
}
.thumbnail-img {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
  border: 1px solid #ddd;
}

.image-popover {
  padding: 0 !important;
  background-color: transparent !important;
  box-shadow: none !important;
  border: none !important;
}

.preview-img {
  width: 300px; // 放大图片
  height: auto;
  max-height: 400px;
  display: block;
  object-fit: contain;
  border: none;
  border-radius: 0;
  background: transparent;
}

.thumbnail-download {
  display: none; // 你也可以用按钮代替
}
</style>